package com.ttxs.common.core.utils;


import static com.ttxs.common.core.constant.SecurityConstant.AuthMode;
import com.ttxs.common.core.constant.SecurityConstant;
import com.ttxs.common.core.vo.LoginUser;
import com.ttxs.common.core.vo.Token;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PatternMatchUtils;
import org.springframework.util.StringUtils;

import javax.security.auth.message.AuthException;
import java.util.Collection;
import java.util.Set;
import java.util.function.BiFunction;

public class AuthUtils {

    private static AntPathMatcher antPathMatcher = new AntPathMatcher();

    public static boolean isLogin(String token) {
        return TokenUtils.isLogin(token);
    }

    /**
     * 创建token，并缓存LoginUser到redis
     * @param loginUser
     * @return
     */
    public static Token createToken(LoginUser loginUser) {
        return TokenUtils.createToken(loginUser);
    }

    public static Token createOrRefreshToken(LoginUser loginUser, String token) {
        return TokenUtils.createToken(loginUser, token);
    }

    public static LoginUser getLoginUser(String token) {
        return TokenUtils.getLoginUser(token);
    }

    /**
     *
     * 如果是rest，authority为GET_/users/{id}形式
     * 如果是url，authority为//users/get?id=xxx形式
     * 如果是perms，authority为sys:user:get形式
     * @param authority
     * @param token
     * @return
     */
    public static boolean hasPerms(String authority, String token) {
        LoginUser loginUser = getLoginUser(token);
        AuthMode authMode = loginUser.getAuthMode();
        if(authMode == SecurityConstant.AuthMode.PERMS) {
            return match(authority, loginUser.getAuthorities(), PatternMatchUtils::simpleMatch);
        } else if (authMode == SecurityConstant.AuthMode.REST || authMode == AuthMode.URL) {
            return match(authority, loginUser.getAuthorities(), AuthUtils::apply);
        }
        throw new RuntimeException("不支持的授权模式：" + authMode);
    }

    /**
     * 通过AntPathMatcher检查paths是否包含了path
     * @param paths
     * @param path
     * @return
     */
    public static boolean contains(Set<String> paths, String path) {
        return match(path, paths, AuthUtils::apply);
    }

    public static void removeToken(String token) {
        TokenUtils.logout(token);
    }

    private static boolean match(String authority, Set<String> authorities, BiFunction<String, String, Boolean> biFunction) {
        if(!StringUtils.hasText(authority)) return false;
        if(authorities == null || authorities.isEmpty()) return false;
        for (String pattern : authorities) {
            if(biFunction.apply(pattern, authority)) {
                return true;
            }
        }
        return false;
    }

    private static Boolean apply(String pattern, String path) {
        return antPathMatcher.match(pattern, path);
    }

}
